#pragma once
#include <atomic>
#include <vector>
#include <string>
#include <queue>
#include <mutex>
#include <thread>
#include <iostream>
#include "rclcpp/rclcpp.hpp"
#include <std_msgs/msg/u_int8.hpp>
#include <std_msgs/msg/u_int8_multi_array.hpp>
#include <std_msgs/msg/u_int16.hpp>
#include <std_msgs/msg/u_int16_multi_array.hpp>
#include "param_struct.h"
#include "io_macro.h"
#include "TimeStamp.h"
#define MAX_CHANNEL 8     // 最大支持8路即 8*8=64位io
#define DI_QUEUE_SIZE 5   // 输入队列长度
#define DO_QUEUE_SIZE 5   // 输出队列长度
#define MAX_TIME_OUT 1000 // 1000ms

#define MAX_ANALOG_CHANNEL 16 // 每个模块最大支持16路(可扩展增大)
namespace io_module {
// 最大支持单个模块64路输入 64路输出
class BaseInterface
{
public:
    std::shared_ptr<rclcpp::Node> node_;
    explicit BaseInterface(const std::shared_ptr<rclcpp::Node>& node):node_(node) {}

    BaseInterface(const std::shared_ptr<rclcpp::Node>& node, ModuleParam param):
        node_(node), m_moduleParam(param), m_dataTime(node), m_analogDataTime(node)
    {
        DEBUG_STREAM_OUT("creat obj interface_type=" << m_moduleParam.interface_type);
    }

    virtual ~BaseInterface() {}

    // 输入输出原子类型
    using U8_ATOMIC_TYPE = std::atomic<uint8_t>;

    // 输入输出原子类型
    using U16_ATOMIC_TYPE = std::atomic<uint16_t>;

    using WORD = uint16_t;

    // 初始化函数
    virtual bool init() = 0;

    // 获取模块的参数
    virtual ModuleParam getModuleParam() const { return m_moduleParam; }

    // 获取模块的序号
    virtual uint8_t getModuleNumber() const { return m_moduleParam.module_number; }

    // 判断是否topic不发送，数据不刷新
    virtual bool dataTimeOut() { return m_dataTime.timed_out(MAX_TIME_OUT); }

    // 更新当前时间戳
    virtual void updateTime() { m_dataTime.update(); }

    // 判断是否模拟量topic不发送，数据不刷新
    virtual bool dataTimeOutA() { return m_analogDataTime.timed_out(MAX_TIME_OUT); }

    // 更新当前模拟量时间戳
    virtual void updateTimeA() { m_analogDataTime.update(); }

    // 单点控制io输出
    virtual bool setOutput(const uint8_t &index, const bool &level) = 0;

    // 将当前模块的输入状态一次性读取出来
    virtual bool readInput(uint64_t& result) = 0;

    // 单路控制模拟量输出
    virtual bool setOutputA(const uint8_t &index, const WORD &rawData) = 0;

    // 将当前模块的模拟量输入状态一次性读取出来
    virtual bool readInputA(std::vector<WORD> &result) = 0;

protected:
    ModuleParam m_moduleParam;
    // 刷新输入io topic是否实时存在
    CTimeStamp m_dataTime;
    // 刷新输入模拟量 topic是否实时存在
    CTimeStamp m_analogDataTime;
    // 输出缓冲字节数组
    std::array<U8_ATOMIC_TYPE, MAX_CHANNEL> do_bytes;
    // 输入缓冲字节数组
    std::array<U8_ATOMIC_TYPE, MAX_CHANNEL> di_bytes;
    // 输出缓冲word数组
    std::array<U16_ATOMIC_TYPE, MAX_ANALOG_CHANNEL> ao_words;
    // 输入缓冲word数组
    std::array<U16_ATOMIC_TYPE, MAX_ANALOG_CHANNEL> ai_words;
};
} // end_namespace
